﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using IURIP;
using System.Xml;

namespace URIP.Core
{
    public abstract class BaseRunable : IRunable
    {
        public BaseRunable(ITemplate template, IRunable parentRunable)
        {
            m_template = template;
            m_parentRunable = parentRunable;
        }

        protected ITemplate m_template = null;
        protected IRunable m_parentRunable = null;
        protected XmlNode m_tgtWorkOnNode = null;
        /// <summary>
        /// Indicates that the runable object is broken or not.
        /// </summary>
        protected bool m_broken = true;

        public ITask Task
        {
            get { return m_template.Task; }
        }
        public ITemplate Template
        {
            get { return m_template; }
        }
        public ITarget Target
        {
            get { return m_template.Target; }
        }
        public IProcess Process
        {
            get 
            {
                if (this is IProcess)
                {
                    return (IProcess)this;
                }
                else
                {
                    return ParentRunable == null ? null : ParentRunable.Process;
                }
            }
        }
        public IAction Action
        {
            get 
            {
                if (this is IAction)
                {
                    return (IAction)this;
                }
                else 
                {
                    return ParentRunable == null ? null : ParentRunable.Action;
                }
            }
        }
        public IRunable ParentRunable
        {
            get { return m_parentRunable; }
        }
        public XmlNode TgtWorkOnNode
        {
            get { return m_tgtWorkOnNode; }
        }

        private bool CheckBreakpoint()
        {
            m_broken = true;
            bool hasLogged = false;
            while (Template.HasBreakPoint && this.m_broken)
            {
                //@@ If stop the process in pause state, it should go out
                if (this.CheckStop())
                {
                    return true;
                }
                if (!hasLogged)
                {
                    Task.Logger.LogInfo("The task meets a breakpoint.");
                    hasLogged = true;
                }
                System.Threading.Thread.Sleep(5);
                Application.DoEvents();
            }
            m_broken = true;
            return false;
        }
        private bool CheckPause()
        {
            bool hasLogged = false;
            while (Task.Paused && !Task.Stopped)
            {
                //@@ If stop the process in pause state, it should go out
                if (this.CheckStop())
                {
                    return true;
                }
                if (!hasLogged)
                {
                    Task.Logger.LogInfo("The task is paused.");
                    hasLogged = true;
                }
                System.Threading.Thread.Sleep(5);
                Application.DoEvents();
            }
            return false;
        }
        private bool CheckStop()
        {
            if (Process != null && Process.Stopped)
            {
                Task.Logger.LogInfo("The process is stopped. The next process will run soon.");
                return true;
            }
            return Task.Stopped;
        }
        protected bool CheckOperation()
        {
            if (!this.CheckStop())
            {
                Task.EnterRunableObject(this);
                return (this.CheckPause() || this.CheckBreakpoint());
            }
            return true;
        }

        /// <summary>
        /// The inherite object run its own business function
        /// </summary>
        protected abstract void RunAssis();

        public void Run(XmlNode tgtWorkOnNode)
        {
            if (this.CheckOperation())
            {
                return;
            }
            m_tgtWorkOnNode = tgtWorkOnNode;
            this.RunAssis();
            Task.LeaveRunableObject(this);
        }
        public void PassedBreakPoint()
        {
            m_broken = false;
        }

        protected void RunHelper(LinkedListNode<ITemplate> node, XmlNode xmlNode)
        {
            if (node != null && node.Value != null)
            {
                IRunable runable = node.Value.CreateRunable(this);
                runable.Run(xmlNode);
                if (this.CheckOperation())
                {
                    return;
                }
                RunHelper(node.Next, xmlNode);
            }
        }
        protected LinkedListNode<ITemplate> GetFirstChildNode()
        {
            if (this.Template.ChildrenTemplates.Count > 0)
            {
                return this.Template.ChildrenTemplates.First;
            }
            else
            {
                return null;
            }
        }
    }
}
